In this notebook we explore several algorithmically assisted approaches towards fundamental analysis and investing.
"Algorithmic assistance" here does not impact our investment strategy as such. The strategy is already defined, however, we will write and use plain as well as machine learning
algorithms that will hopefully help us execute our strategy in a more straightforward and informed manner.
Our goal here is finding market inefficiencies in pricing.
In other words, the alpha is gained by finding potentially undervalued (or overvalued) coins, assigning a correct price and making a buy or short decision based on better information.
We will focus on undervalued assets first (as shorting is difficult in current crypto environment). Since
$$Cm = Q * P \text{, where Q is a constant}$$
we can assume perfect correlation between $P$ and $Cm$ as well high dependence of the rate of change of $P$ on the supply to current market cap value. To maximize our strategy it then needs to be restated as trying to find undervalued coins with the highest potential rate of change or, more precisely, trying to find those coins with low market cap and limited supply.
Load notebook specific extensions here
%load_ext autoreload
%autoreload 2
This space is reserved for all imports
import numpy as np
import pandas as pd
from cryptocompy import price as cprice
from coinmarketcap import Market
from ccap import Ccap
import utils
import imp
import seaborn as sns
from IPython.display import Image
from jupyterthemes import jtplot
from ipywidgets import IntProgress
from ipywidgets import Box
from IPython.display import display
import matplotlib.pyplot as plt
from selenium import webdriver
import time
imp.reload(utils)
pd.options.display.float_format = '{:,.6f}'.format
jtplot.style()
We can start by grabbing market data from a coin directory such as coinmarketcap.
This data usually includes our indicators of interest (market cap, price and supply) as well as other, potentially interesting, datapoints.
cmc = Market()
markets = utils.markets_to_df(cmc.ticker()).dropna()
print("Got %d markets with complete information in total." % len(markets))
Here's a quick overview of our markets
markets.head()
And a quick summary of the data
markets.describe()
Lets remember that we are interested in undervalued assets with the highest potential rate of change. Meaning those assets most likely to 2x-3x+ in value.
To do this we need to define our search criteria, mainly max market cap, min market cap, max supply and max price (which is actually optional).
The parameters as well as the filter are defined below.
Note This step can be optimized via machine learning as there must exist a set of parameters leading to the highest returns.
denom = 1000000 # Unit denomination so we don't have to type this out eveyrtime
market_cap_min = 1 * denom # 1m marketcap min
market_cap_max = 45 * denom # 45m marketcap max
supply_max = 200 * denom # Total supply of no more than 900m
price_max = 0.20 # Current max price in USD
markets = utils.filter_by_market_cap(markets, market_cap_min, market_cap_max)
markets = utils.filter_by_total_supply(markets, supply_max)
markets = utils.filter_by_price(markets, price_max)
print("Got %d valid markets." % len(markets))
print("Sorting by current market cap.")
sorted_markets = markets.sort_values('market_cap_usd')
sorted_markets
Above we got 89 potential coins that fit our previously defined criteria.
Now applying the 80/20 rule, most of these coins will be useless and we need to get to the 20% which aren't.
We need to define an additional filter that will hopefully help us in reducing the noise before we can begin actually analyzing these assets.
Here we grab OHLC data for each of our coins and only look at coins that showed a positive price trend over the past 7 days.
symbols = sorted_markets['symbol'].values # our coins
ohlc = {}
l = len(symbols)
prog = IntProgress(min=0, max=l, value=10, description="Grabbing data: ")
display(prog)
for i, symbol in enumerate(symbols):
d = pd.DataFrame(cprice.get_historical_data(symbol, 'BTC', 'day', limit=7))
ohlc[symbol] = d
prog.value += 1
Defining and running our price filter.
outliers = []
for symbol in ohlc:
df = ohlc[symbol]
if 'close' in df:
f = df['close'].head(1).values[0]
l = df['close'].tail(1).values[0]
if l > f:
outliers.append(symbol)
print("Found outliers: ", outliers)
Lets graph these coins.
for symbol in outliers:
plt.plot(ohlc[symbol].close, label=symbol)
plt.legend(shadow=False, fancybox=True)
plt.show()
We have managed to reduce our original set of 89 coins to 10 potentially undervalued coins.
Here we do some light analysis of those coins. Most of these steps are performed manually right now with only minor algorithmic assistance.
In the future we could develop a whole toolset to help us automate the whole process!
Some utility functions as well as the actual analysis step follow below.
# Utility functions
ccap = Ccap()
br.quit()
br = webdriver.PhantomJS()
br.set_window_size(1024,768)
def get_coin_stats(market):
"""
Extracts supply, marketcap and price from
coin market data.
"""
supply = int(market['available_supply'])
mcap = market['market_cap_usd'].values[0]
p = market['price_usd'].values[0]
return supply, mcap, p
def get_and_prettify_stats(market):
"""
Calls 'get_coin_stats' and pretty prints results.
"""
s, m, p = get_coin_stats(market)
print("Supply: {}, Marketcap: ${:,.2f}, Price: ${:,.2f}".format(s, m, p))
def capture_site(site, name):
"""
Take a screencapture of any given site.
"""
br.get(site)
time.sleep(3)
br.save_screenshot('/tmp/{}.png'.format(name))
def create_coin_summary(coin):
"""
Calls 'get_and_prettify_stats' as well as
grabs some additional information about the coin (like its official website).
"""
market = sorted_markets[sorted_markets["symbol"] == coin]
name = market.name.values[0]
print("Investigating coin: {}".format(name))
get_and_prettify_stats(market)
print("Getting coin's website ")
website, exchanges = ccap.info(name)
print("Coin available at: {} and trading at {} exchanges.".format(website, len(exchanges)))
return name, website, exchanges
def coin_summary_with_screenshot(coin):
"""
Performs all above steps at once.
"""
name, website, exchanges = create_coin_summary(coin)
print("Taking screenshot")
capture_site(website, name)
display(Image("/tmp/{}.png".format(name), width=120, height=120))
coin_summary_with_screenshot('XTO')
Website completely unclear. No clue what this project is about and what problems are being addressed. Safe to move on.
coin_summary_with_screenshot('TZC')
A fairly young "store of value" coin, aims to be a more secure and faster bitcoin. Official description:
TrezarCoin is a high secure store of value with fast transaction times designed to be used as a currency.
We implemented the newest Proof-of-Work algorithm, as well as Proof-of-Stake, to meet these stringet security standards.
Emphasis is given to PoW, PoS and security in general, which is a major shortcoming of the bitcoin protocol. Both PoW and PoS appear to be implemented and working already, so not just talk. This is a major plus. Runs on its own chain, can be mined but is ASIC resistant, which inherently guarantees gradual price inflation. Devs also emphasize speed of transactions, another major disadvantage of bitcoin. Development is ongoing and the team has already released a wallet for all major OSes, mobile apps are in the works. Stacking of coins (a dividend payment structure of the crypto world) is already implemented
and working too!
Unfortunately hard to find detailed information on team members which might be a red flag but could also be forgiven seeing as the project is very new and the website is still being worked on.
Very active github, working wallets, working chain, working mining pools, working stacking!
Also, majority of the code is written in C++, a sign of experienced devs working on this project.
Very active bitcointalk thread. Slack, telegram and twitter all already setup and actively used as communication channels. Young subreddit exists but not in wide use. Also, shilling pretty much non-existent right now, pointing towards most people being unaware or uninterested in this coin at this moment.
Only listed on 3 very, very shitty exchanges. This is great because a real exchange might drive the price up significantly, provided the team is actively working on one. Theoretically, with its own chain and wallets, there's nothing preventing a real exchange picking up this coin.
The coin is designed to store value (deflationary) and with such a tiny marketcap, current price and limited supply appears to be a guaranteed 2x-3x once its listed on an actual proper exchange. If the dev team is as solid as it appears to be and if the team provides means to establish this, then this project appears to be severely undervalued right now.